//################################################################################
// MIT License
// Copyright (c) 2024 ZhangYihua
//
// Change Logs:
// Date           Author       Notes
// 2023-05-14     ZhangYihua   first version
//
// Description  : 
//################################################################################

// phase[0:2*PI] map to rd_addr[0:PI/4]
module cos_sin_map #(
parameter           NEG_SIN                 = 1'b0,     // 1'b0:normal; 1'b1:invert sin;
parameter           PHS_DW                  = 11,

// the following parameters are calculated automatically
parameter           TAB_AW                  = PHS_DW-3
) ( 
input                                       rst_n,
input                                       clk,
input                                       cke,

input               [PHS_DW-1:0]            phase,
output  reg         [TAB_AW-1:0]            rd_addr,
output  reg                                 rd_swap,
output  reg                                 rd_cinv,
output  reg                                 rd_sinv
);

//################################################################################
// define local varialbe and localparam
//################################################################################

wire                [TAB_AW-1:0]            phase_low;
wire                [TAB_AW-1:0]            phase_mir;

//################################################################################
// main
//################################################################################

assign phase_low = phase[0+:TAB_AW];
assign phase_mir = {TAB_AW{1'b1}} - phase_low;

always@(posedge clk or negedge rst_n) begin
    if (rst_n==1'b0) begin
        rd_addr <=`U_DLY {TAB_AW{1'b0}};
        rd_swap <=`U_DLY 1'b0;
        rd_cinv <=`U_DLY 1'b0;
        rd_sinv <=`U_DLY 1'b0;
    end else if (cke==1'b1) begin
        case(phase[PHS_DW-1-:3])
            3'b000  : {rd_addr, rd_swap, rd_cinv, rd_sinv} <=`U_DLY {phase_low, 1'b0, 1'b0,  NEG_SIN};
            3'b001  : {rd_addr, rd_swap, rd_cinv, rd_sinv} <=`U_DLY {phase_mir, 1'b1, 1'b0,  NEG_SIN};
            3'b010  : {rd_addr, rd_swap, rd_cinv, rd_sinv} <=`U_DLY {phase_low, 1'b1, 1'b1,  NEG_SIN};
            3'b011  : {rd_addr, rd_swap, rd_cinv, rd_sinv} <=`U_DLY {phase_mir, 1'b0, 1'b1,  NEG_SIN};

            3'b100  : {rd_addr, rd_swap, rd_cinv, rd_sinv} <=`U_DLY {phase_low, 1'b0, 1'b1, ~NEG_SIN};
            3'b101  : {rd_addr, rd_swap, rd_cinv, rd_sinv} <=`U_DLY {phase_mir, 1'b1, 1'b1, ~NEG_SIN};
            3'b110  : {rd_addr, rd_swap, rd_cinv, rd_sinv} <=`U_DLY {phase_low, 1'b1, 1'b0, ~NEG_SIN};
            default : {rd_addr, rd_swap, rd_cinv, rd_sinv} <=`U_DLY {phase_mir, 1'b0, 1'b0, ~NEG_SIN};
        endcase
    end else
        ;
end

//################################################################################
// ASSERTION
//################################################################################

`ifdef CBB_ASSERT_ON
// synopsys translate_off


// synopsys translate_on
`endif

endmodule
